package com.dragon.sdgp.util;

import com.dragon.sdgp.common.exception.DataTypeException;
import com.dragon.sdgp.entity.LexiconItem;
import com.dragon.sdgp.service.LexiconService;
import com.dragon.sdgp.service.impl.LexiconServiceImpl;
import com.dragon.sdgp.util.defaultGenerate.DefaultDataGenerateUtil;
import com.dragon.sdgp.util.defaultGenerate.strategy.*;
import com.dragon.sdgp.util.regexpDecode.RegExpDataGenerateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @AUTHOR : Dragon_Yang
 * @File : CreateUtil
 * @DESCRIPTION :
 * @DATE : 2023/3/14 18:23
 */
@Component
public class CreateUtil {

    @Autowired
    private LexiconService lexiconService;

    private static Map<String, List<String>> dataMapList = new HashMap<>();
    private static LinkedList<String> lexiconList = null;
    private static boolean repeat = true;

    /**
     * type:[0:int][1:varchar][2:datetime][3:tinyint]
     * sourceType:[0:随机][1:正则][2:词库][3:递增][4:递减][5:固定][6:智能]
     * sourceVal:[0:人名][1:性别][2:省份][3:城市][4:车牌][5:日期]
     *
     * @param count
     * @param columns
     * @return
     */
    public List<Map<String, String>> createDataList(int count, List<Map<String, String>> columns){
        List<Map<String, String>> data = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Map<String, String> dataItem = new HashMap<>();
            for (Map<String, String> column : columns) {
                int sourceType = Integer.parseInt(column.get("sourceType"));
                int typeVal = Integer.parseInt(column.get("typeVal"));
                String sourceVal = (column.get("sourceVal"));
                String columnName = column.get("columnName");
                switch (sourceType){
                    case 0:{
                        dataItem.put(columnName, randomCreate(columnName, count, i, typeVal));
                        break;
                    }
                    case 1:{
                        if(!dataMapList.containsKey(columnName)){
                            dataMapList.put(columnName, RegExpDataGenerateUtil.createDataList(count, sourceVal));
                        }
                        dataItem.put(columnName, getDataMapList(columnName, i, typeVal));
                        break;
                    }
                    case 2:{
                        dataItem.put(columnName, LexiconCreate(count, sourceVal, typeVal));
                        break;
                    }
                    case 3:{
                        dataItem.put(columnName, autoIncreaseOrDescent(Integer.parseInt(sourceVal), i, typeVal, 1));
                        break;
                    }
                    case 4:{
                        dataItem.put(columnName, autoIncreaseOrDescent(Integer.parseInt(sourceVal), i, typeVal, -1));
                        break;
                    }
                    case 5:{
                        dataItem.put(columnName, sourceVal);
                        break;
                    }
                    case 6:{
                        dataItem.put(columnName, defaultCreate(columnName, sourceVal, count, i, typeVal));
                        break;
                    }
                }
            }
            data.add(dataItem);
        }
        dataMapList.clear();
        lexiconList = null;
        return data;
    }

    private String LexiconCreate(int count, String sourceVal, int typeVal) {
        if(lexiconList == null){
            lexiconList = new LinkedList<>();
            String[] strings = (String[]) lexiconService.getLexiconItem(Integer.parseInt(sourceVal)).getData();
            for (String s : strings) {
                lexiconList.push(s);
            }
            if(lexiconList.size() >= count) repeat = false;
        }
        String res = null;
        if(repeat){
            res = lexiconList.get(CommonUtil.getRandom(lexiconList.size()));
        }else {
            int index = CommonUtil.getRandom(lexiconList.size());
            res = lexiconList.get(index);
            lexiconList.remove(index);
        }
        checkType(typeVal, res);
        return res;
    }

    private static String defaultCreate(String columnName, String sourceVal, int count, int index, int typeVal) {
        if(!dataMapList.containsKey(columnName)){
            switch (Integer.parseInt(sourceVal)){
                case 0:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new PersonNameGenerateStrategy()));
                    break;
                }
                case 1:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new GenderStrategy()));
                    break;
                }
                case 2:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new ProvinceGenerateStrategy()));
                    break;
                }
                case 3:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new CityGenerateStrategy()));
                    break;
                }
                case 4:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new LicensePlateGenerateStrategy()));
                    break;
                }
                case 5:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new DateTimeGenerateStrategy()));
                    break;
                }
                case 6:{
                    dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new PhoneNumberGenerateStrategy()));
                    break;
                }
            }
        }
        return getDataMapList(columnName, index, typeVal);
    }


    private static String autoIncreaseOrDescent(int start, int index, int typeVal, int direction){
        if(typeVal == 0){
            return String.valueOf(start + (index * direction));
        }else {

        }
        return null;
    }

    private static String randomCreate(String columnName, int count, int index, int typeVal){
        if(typeVal == 0){
            return String.valueOf(CommonUtil.getRandom(Integer.MAX_VALUE));
        }else if(typeVal == 2){
            if(!dataMapList.containsKey(columnName)){
                dataMapList.put(columnName, DefaultDataGenerateUtil.getList(count, new DateTimeGenerateStrategy()));
            }
            return getDataMapList(columnName, index, typeVal);
        }else if(typeVal == 1){
            if(!dataMapList.containsKey(columnName)){
                dataMapList.put(columnName, RegExpDataGenerateUtil.createDataList(count, "[0-9a-zA-Z]{1, 20}"));
            }
            return getDataMapList(columnName, index, typeVal);
        }else if(typeVal == 3){
            return String.valueOf(CommonUtil.getRandom(Byte.MAX_VALUE + 1));
        }
        return null;
    }

    private static String getDataMapList(String columnName, int index, int typeVal){
        String val = dataMapList.get(columnName).get(index);
        checkType(typeVal, val);
        return val;
    }

    private static void checkType(int typeVal, String val){
        if(typeVal == 0 || typeVal == 3){
            try{
                Integer.parseInt(val);
            }catch (Exception e){
                throw new DataTypeException("错误：int 和 tinyint 类型不能生成0-9以外的字符!");
            }
        }
    }
}
